import * as signalR from '@microsoft/signalr'

interface SignalRConfig {
  authHubUrl?: string      // 登录模块Hub地址
  inventoryHubUrl?: string // 库存模块Hub地址
  enableLogging?: boolean
  reconnectDelays?: number[]
  maxReconnectAttempts?: number
  heartbeatInterval?: number
}

interface ClientInfo {
  clientId: string
  userId?: string
  userName?: string
  sessionId?: string
  connectionTime: Date
  userAgent: string
  moduleAccess: string[]  // 可访问的模块列表
  lastActivity: Date
}

interface HubConnectionInfo {
  connection: signalR.HubConnection
  isConnected: boolean
  reconnectAttempts: number
  lastConnectTime: Date | null
  lastHeartbeat: Date | null
  hubType: 'auth' | 'inventory'
  endpoint: string
}

interface CrossClientMessage {
  messageId: string
  sourceClientId: string
  targetClientIds?: string[]  // 空表示广播
  messageType: string
  payload: any
  timestamp: Date
  module: string
}

class DistributedSignalRService {
  // 连接管理
  private connections: Map<string, HubConnectionInfo> = new Map()
  
  // 事件回调管理
  private eventCallbacks: Map<string, Function[]> = new Map()
  
  // 客户端信息
  private clientInfo: ClientInfo
  
  // 在线客户端列表
  private onlineClients: Map<string, ClientInfo> = new Map()
  
  // 心跳定时器
  private heartbeatTimer: number | null = null
  
  // 配置
  private config: SignalRConfig = {
    authHubUrl: 'http://localhost:5088/UserHub',           // 登录模块Hub
    inventoryHubUrl: 'http://localhost:5215/InventoryReadHub', // 库存模块Hub
    enableLogging: true,
    reconnectDelays: [0, 2000, 5000, 10000, 30000],      // 重连延迟策略
    maxReconnectAttempts: 10,
    heartbeatInterval: 30000 // 30秒心跳
  }

  constructor() {
    this.clientInfo = this.generateClientInfo()
    this.initializeEventSystem()
  }

  // 生成客户端信息
  private generateClientInfo(): ClientInfo {
    return {
      clientId: this.generateClientId(),
      connectionTime: new Date(),
      userAgent: navigator.userAgent,
      moduleAccess: ['inventory', 'statistics'], // 默认可访问模块
      lastActivity: new Date()
    }
  }

  // 生成唯一客户端ID
  private generateClientId(): string {
    const timestamp = Date.now().toString(36)
    const randomStr = Math.random().toString(36).substring(2, 8)
    return `client_${timestamp}_${randomStr}`
  }

  // 初始化事件系统
  private initializeEventSystem(): void {
    // 注册内置事件监听器
    this.addEventListener('ClientConnected', this.onClientConnected.bind(this))
    this.addEventListener('ClientDisconnected', this.onClientDisconnected.bind(this))
    this.addEventListener('DataChanged', this.onDataChanged.bind(this))
    this.addEventListener('InventoryUpdated', this.onInventoryUpdated.bind(this))
  }

  // 配置服务
  configure(config: Partial<SignalRConfig>): void {
    this.config = { ...this.config, ...config }
  }

  // 设置用户信息
  setUserInfo(userId: string, userName: string, sessionId?: string): void {
    this.clientInfo.userId = userId
    this.clientInfo.userName = userName
    this.clientInfo.sessionId = sessionId
    this.clientInfo.lastActivity = new Date()
  }

  // 启动所有连接
  async start(): Promise<void> {
    console.log('🚀 启动分布式SignalR服务...')
    console.log('📋 客户端信息:', this.clientInfo)

    try {
      // 并行启动多个Hub连接
      const connectionPromises = []

      // 启动认证Hub连接
      if (this.config.authHubUrl) {
        connectionPromises.push(this.startHubConnection('auth', this.config.authHubUrl))
      }

      // 启动库存Hub连接
      if (this.config.inventoryHubUrl) {
        connectionPromises.push(this.startHubConnection('inventory', this.config.inventoryHubUrl))
      }

      await Promise.all(connectionPromises)

      // 启动心跳机制
      this.startHeartbeat()

      console.log('✅ 分布式SignalR服务启动完成')
      console.log('🔗 活跃连接:', Array.from(this.connections.keys()))

    } catch (error) {
      console.error('❌ 分布式SignalR服务启动失败:', error)
      throw error
    }
  }

  // 启动单个Hub连接
  private async startHubConnection(hubType: 'auth' | 'inventory', hubUrl: string): Promise<void> {
    try {
      // 如果连接已存在且已连接，跳过
      const existingConnection = this.connections.get(hubType)
      if (existingConnection?.isConnected) {
        console.log(`🔄 ${hubType} Hub已连接，跳过重复连接`)
        return
      }

      // 创建连接
      const connection = new signalR.HubConnectionBuilder()
        .withUrl(hubUrl, {
          withCredentials: false,
          headers: {
            'Client-Id': this.clientInfo.clientId,
            'User-Id': this.clientInfo.userId || '',
            'Session-Id': this.clientInfo.sessionId || ''
          }
        })
        .withAutomaticReconnect(this.config.reconnectDelays || [0, 2000, 5000, 10000, 30000])
        .configureLogging(this.config.enableLogging ? signalR.LogLevel.Information : signalR.LogLevel.Error)
        .build()

      // 设置连接事件
      this.setupConnectionEvents(connection, hubType, hubUrl)

      // 设置消息监听器
      this.setupHubMessageListeners(connection, hubType)

      // 启动连接
      await connection.start()

      // 注册连接信息
      const connectionInfo: HubConnectionInfo = {
        connection,
        isConnected: true,
        reconnectAttempts: 0,
        lastConnectTime: new Date(),
        lastHeartbeat: new Date(),
        hubType,
        endpoint: hubUrl
      }

      this.connections.set(hubType, connectionInfo)

      // 注册客户端到Hub
      await this.registerClientToHub(connection, hubType)

      console.log(`✅ ${hubType} Hub连接成功: ${hubUrl}`)

    } catch (error) {
      console.error(`❌ ${hubType} Hub连接失败:`, error)
      throw error
    }
  }

  // 设置连接事件
  private setupConnectionEvents(connection: signalR.HubConnection, hubType: string, hubUrl: string): void {
    connection.onclose((error) => {
      const connectionInfo = this.connections.get(hubType)
      if (connectionInfo) {
        connectionInfo.isConnected = false
      }
      console.log(`🔌 ${hubType} Hub连接已断开:`, error?.message || '未知原因')
      this.triggerEvent('ConnectionClosed', { hubType, error })
    })

    connection.onreconnecting((error) => {
      console.log(`🔄 ${hubType} Hub正在重连...`, error?.message || '')
      this.triggerEvent('Reconnecting', { hubType, error })
    })

    connection.onreconnected((connectionId) => {
      const connectionInfo = this.connections.get(hubType)
      if (connectionInfo) {
        connectionInfo.isConnected = true
        connectionInfo.lastConnectTime = new Date()
        connectionInfo.reconnectAttempts = 0
      }
      console.log(`✅ ${hubType} Hub重连成功, 连接ID: ${connectionId}`)
      this.triggerEvent('Reconnected', { hubType, connectionId })
      
      // 重新注册客户端
      this.registerClientToHub(connection, hubType)
    })
  }

  // 注册客户端到Hub
  private async registerClientToHub(connection: signalR.HubConnection, hubType: string): Promise<void> {
    try {
      // 加入监控组
      await connection.invoke('JoinMonitoringGroup', 'global')
      await connection.invoke('JoinMonitoringGroup', `module_${hubType}`)
      
      if (this.clientInfo.userId) {
        await connection.invoke('JoinMonitoringGroup', `user_${this.clientInfo.userId}`)
      }

      // 注册客户端信息
      await connection.invoke('RegisterClient', {
        ...this.clientInfo,
        hubType,
        capabilities: this.getClientCapabilities(hubType)
      })

      console.log(`📝 客户端已注册到 ${hubType} Hub`)

    } catch (error) {
      console.error(`❌ 注册客户端到 ${hubType} Hub失败:`, error)
    }
  }

  // 获取客户端能力
  private getClientCapabilities(hubType: string): string[] {
    const capabilities = ['realtime-updates', 'cross-client-sync']
    
    if (hubType === 'inventory') {
      capabilities.push('inventory-monitoring', 'statistics-dashboard')
    } else if (hubType === 'auth') {
      capabilities.push('user-notifications', 'session-management')
    }
    
    return capabilities
  }

  // 设置Hub消息监听器
  private setupHubMessageListeners(connection: signalR.HubConnection, hubType: string): void {
    // 通用跨客户端消息
    connection.on('CrossClientMessage', (message: CrossClientMessage) => {
      this.handleCrossClientMessage(message)
    })

    // 客户端列表更新
    connection.on('ClientListUpdated', (clients: ClientInfo[]) => {
      this.updateOnlineClients(clients)
    })

    // 根据Hub类型设置特定监听器
    if (hubType === 'inventory') {
      this.setupInventoryListeners(connection)
    } else if (hubType === 'auth') {
      this.setupAuthListeners(connection)
    }

    // 通用系统消息
    connection.on('SystemMessage', (message) => {
      console.log(`📢 系统消息 (${hubType}):`, message)
      this.triggerEvent('SystemMessage', { hubType, message })
    })

    // 心跳响应
    connection.on('HeartbeatResponse', (timestamp) => {
      const connectionInfo = this.connections.get(hubType)
      if (connectionInfo) {
        connectionInfo.lastHeartbeat = new Date(timestamp)
      }
    })
  }

  // 设置库存相关监听器
  private setupInventoryListeners(connection: signalR.HubConnection): void {
    // 库存数据更新监听器
    const inventoryEvents = [
      'ReceiveInventoryQuantityRatio',
      'ReceiveInventoryAmountRatio', 
      'ReceiveInOutboundStatistics',
      'ReceiveInOutboundRanking',
      'ReceiveDashboardData',
      'ReceiveInboundSuccess',
      'ReceiveOutboundSuccess',
      'ReceiveLowStockAlert',
      'ReceiveInventoryUpdate'
    ]

    inventoryEvents.forEach(eventName => {
      connection.on(eventName, (data) => {
        console.log(`📊 收到库存事件 ${eventName}:`, data)
        
        // 触发本地事件
        this.triggerEvent(eventName, data)
        
        // 广播跨客户端消息
        this.broadcastToOtherClients({
          messageType: eventName,
          payload: data,
          module: 'inventory'
        })
      })
    })
  }

  // 设置认证相关监听器
  private setupAuthListeners(connection: signalR.HubConnection): void {
    connection.on('UserLoginNotification', (data) => {
      console.log('🔔 用户登录通知:', data)
      this.triggerEvent('UserLoginNotification', data)
    })

    connection.on('SessionExpired', (data) => {
      console.log('⚠️ 会话过期:', data)
      this.triggerEvent('SessionExpired', data)
    })

    connection.on('UserPermissionChanged', (data) => {
      console.log('🔐 用户权限变更:', data)
      this.triggerEvent('UserPermissionChanged', data)
    })
  }

  // 处理跨客户端消息
  private handleCrossClientMessage(message: CrossClientMessage): void {
    // 忽略自己发送的消息
    if (message.sourceClientId === this.clientInfo.clientId) {
      return
    }

    console.log('📨 收到跨客户端消息:', message)
    
    // 更新最后活动时间
    this.clientInfo.lastActivity = new Date()
    
    // 触发相应事件
    this.triggerEvent('CrossClientMessage', message)
    this.triggerEvent(message.messageType, {
      ...message.payload,
      _crossClient: true,
      _sourceClient: message.sourceClientId
    })
  }

  // 广播消息到其他客户端
  async broadcastToOtherClients(message: Omit<CrossClientMessage, 'messageId' | 'sourceClientId' | 'timestamp'>): Promise<void> {
    const fullMessage: CrossClientMessage = {
      messageId: this.generateMessageId(),
      sourceClientId: this.clientInfo.clientId,
      timestamp: new Date(),
      ...message
    }

    // 根据模块选择对应的Hub连接
    const hubType = message.module === 'auth' ? 'auth' : 'inventory'
    const connectionInfo = this.connections.get(hubType)

    if (connectionInfo?.isConnected) {
      try {
        await connectionInfo.connection.invoke('BroadcastToClients', fullMessage)
        console.log(`📤 消息已广播到其他客户端 (${hubType}):`, message.messageType)
      } catch (error) {
        console.error('❌ 广播消息失败:', error)
      }
    }
  }

  // 发送消息到特定客户端
  async sendToClient(targetClientId: string, message: Omit<CrossClientMessage, 'messageId' | 'sourceClientId' | 'timestamp' | 'targetClientIds'>): Promise<void> {
    const fullMessage: CrossClientMessage = {
      messageId: this.generateMessageId(),
      sourceClientId: this.clientInfo.clientId,
      targetClientIds: [targetClientId],
      timestamp: new Date(),
      ...message
    }

    const hubType = message.module === 'auth' ? 'auth' : 'inventory'
    const connectionInfo = this.connections.get(hubType)

    if (connectionInfo?.isConnected) {
      try {
        await connectionInfo.connection.invoke('SendToClient', targetClientId, fullMessage)
        console.log(`📤 消息已发送到客户端 ${targetClientId}:`, message.messageType)
      } catch (error) {
        console.error('❌发送消息失败:', error)
      }
    }
  }

  // 发送消息给所有库存Hub连接的用户
  async sendToAllInventoryUsers(eventName: string, data: any): Promise<void> {
    const connectionInfo = this.connections.get('inventory')
    
    if (connectionInfo?.isConnected) {
      try {
        // 尝试调用Hub方法向所有连接的用户发送消息
        await connectionInfo.connection.invoke('SendToAllInGroup', 'InventoryUsers', eventName, data)
        console.log(`📤 消息已发送给所有库存用户: ${eventName}`)
      } catch (error) {
        console.warn('SendToAllInGroup方法失败，尝试广播方式:', error)
        try {
          // 降级到广播方式
          await this.broadcastToOtherClients({
            messageType: eventName,
            payload: data,
            module: 'inventory'
          })
          console.log(`📤 已通过广播方式发送消息: ${eventName}`)
        } catch (broadcastError) {
          console.error('❌ 广播发送也失败:', broadcastError)
          throw broadcastError
        }
      }
    } else {
      console.warn('⚠️ 库存Hub未连接，无法发送消息')
      throw new Error('库存Hub未连接')
    }
  }

  // 生成消息ID
  private generateMessageId(): string {
    return `msg_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`
  }

  // 更新在线客户端列表
  private updateOnlineClients(clients: ClientInfo[]): void {
    this.onlineClients.clear()
    clients.forEach(client => {
      this.onlineClients.set(client.clientId, client)
    })
    
    console.log(`👥 在线客户端更新: ${clients.length} 个客户端`)
    this.triggerEvent('OnlineClientsUpdated', clients)
  }

  // 启动心跳机制
  private startHeartbeat(): void {
    if (this.heartbeatTimer) {
      clearInterval(this.heartbeatTimer)
    }

    this.heartbeatTimer = setInterval(async () => {
      await this.sendHeartbeat()
    }, this.config.heartbeatInterval!) as any
  }

  // 发送心跳
  private async sendHeartbeat(): Promise<void> {
    const heartbeatData = {
      clientId: this.clientInfo.clientId,
      timestamp: new Date(),
      status: 'active'
    }

    for (const [hubType, connectionInfo] of this.connections) {
      if (connectionInfo.isConnected) {
        try {
          await connectionInfo.connection.invoke('Heartbeat', heartbeatData)
        } catch (error) {
          console.warn(`⚠️ ${hubType} Hub心跳失败:`, error)
        }
      }
    }
  }

  // 事件系统
  addEventListener(eventName: string, callback: Function): void {
    if (!this.eventCallbacks.has(eventName)) {
      this.eventCallbacks.set(eventName, [])
    }
    this.eventCallbacks.get(eventName)!.push(callback)
  }

  removeEventListener(eventName: string, callback: Function): void {
    const callbacks = this.eventCallbacks.get(eventName)
    if (callbacks) {
      const index = callbacks.indexOf(callback)
      if (index > -1) {
        callbacks.splice(index, 1)
      }
    }
  }

  private triggerEvent(eventName: string, data: any): void {
    const callbacks = this.eventCallbacks.get(eventName)
    if (callbacks) {
      callbacks.forEach(callback => {
        try {
          callback(data)
        } catch (error) {
          console.error(`❌ 事件回调执行失败 (${eventName}):`, error)
        }
      })
    }
  }

  // 内置事件处理器
  private onClientConnected(data: any): void {
    console.log('👋 客户端已连接:', data)
  }

  private onClientDisconnected(data: any): void {
    console.log('👋 客户端已断开:', data)
  }

  private onDataChanged(data: any): void {
    console.log('🔄 数据已变更:', data)
  }

  private onInventoryUpdated(data: any): void {
    console.log('📦 库存已更新:', data)
  }

  // 获取连接状态
  getConnectionStatus(): Record<string, any> {
    const status: Record<string, any> = {
      clientId: this.clientInfo.clientId,
      onlineClients: this.onlineClients.size,
      connections: {}
    }

    for (const [hubType, connectionInfo] of this.connections) {
      status.connections[hubType] = {
        isConnected: connectionInfo.isConnected,
        endpoint: connectionInfo.endpoint,
        lastConnectTime: connectionInfo.lastConnectTime,
        lastHeartbeat: connectionInfo.lastHeartbeat,
        reconnectAttempts: connectionInfo.reconnectAttempts
      }
    }

    return status
  }

  // 获取在线客户端列表
  getOnlineClients(): ClientInfo[] {
    return Array.from(this.onlineClients.values())
  }

  // 检查Hub连接状态
  isHubConnected(hubType: string): boolean {
    return this.connections.get(hubType)?.isConnected || false
  }

  // 获取Hub连接
  getHubConnection(hubType: string): signalR.HubConnection | null {
    return this.connections.get(hubType)?.connection || null
  }

  // 兼容性方法
  get connection(): signalR.HubConnection | null {
    return this.getHubConnection('inventory')
  }

  get isConnected(): boolean {
    return this.isHubConnected('inventory')
  }

  get isInventoryConnected(): boolean {
    return this.isHubConnected('inventory')
  }

  get isUserConnected(): boolean {
    return this.isHubConnected('auth')
  }

  // 停止所有连接
  async stop(): Promise<void> {
    console.log('🛑 停止分布式SignalR服务...')

    // 停止心跳
    if (this.heartbeatTimer) {
      clearInterval(this.heartbeatTimer)
      this.heartbeatTimer = null
    }

    // 停止所有连接
    const stopPromises = []
    for (const [hubType, connectionInfo] of this.connections) {
      if (connectionInfo.connection) {
        stopPromises.push(
          connectionInfo.connection.stop().catch(error => 
            console.error(`❌ 停止 ${hubType} Hub连接失败:`, error)
          )
        )
      }
    }

    await Promise.all(stopPromises)
    
    // 清理状态
    this.connections.clear()
    this.onlineClients.clear()
    this.eventCallbacks.clear()

    console.log('✅ 分布式SignalR服务已停止')
  }
}

// 创建单例实例
export const distributedSignalRService = new DistributedSignalRService()
export default DistributedSignalRService
